package fr.lille.inria.adam.lifl.EcoGardeInventory.Services;

import static fr.lille.inria.adam.lifl.EcoGardeInventory.Utils.CommonUtilities.GET;
import static fr.lille.inria.adam.lifl.EcoGardeInventory.Utils.CommonUtilities.POST;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URLEncoder;
import java.util.ArrayList;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HTTP;

import android.app.IntentService;
import android.content.Intent;
import android.os.Bundle;
import android.os.ResultReceiver;
import android.util.Log;
import fr.lille.inria.adam.lifl.EcoGardeInventory.Utils.ParcelableNameValuePair;

public class ExecuteRequest extends IntentService {

	private int mMethod;
	private String mMessage, mResponse;
	private ArrayList<ParcelableNameValuePair> mParams;
	private ArrayList<ParcelableNameValuePair> mHeaders;
	private HttpRequestBase mRequest;
	private ResultReceiver mReceiver;
	private String mUrl;

	public ExecuteRequest() {
		super("executeRestRequest");
	}

	@Override
	protected void onHandleIntent(Intent mIntent) {
		mParams = mIntent.getParcelableArrayListExtra("params");
		
		mHeaders = mIntent.getParcelableArrayListExtra("headers");
		
		
		mUrl = mIntent.getStringExtra("url");
		mReceiver = (ResultReceiver) mIntent.getParcelableExtra("receiver");
		
		mMethod = (int) mIntent.getIntExtra("method", 1);
		
		try {
			execute(mMethod);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void execute(int mMethod) throws Exception {
		switch (mMethod) {
		
		case GET: {
			String mCombinedParams = "";
			
			if (!mParams.isEmpty()) {
				mCombinedParams += "?";
				for (NameValuePair p : mParams) {
					String mParamString = p.getName() + "="
							+ URLEncoder.encode(p.getValue(), "UTF-8");
					
					if (mCombinedParams.length() > 1) {
						mCombinedParams += "&" + mParamString;
					} else {
						mCombinedParams += mParamString;
					}
				}
			}

			mRequest = new HttpGet(mUrl + mCombinedParams);

			// add headers
			for (NameValuePair h : mHeaders) {
				mRequest.addHeader(h.getName(), h.getValue());
			}

			commit();
			break;
		}
		
		case POST: {
			String mCombinedParams = "";
			
			if (!mParams.isEmpty()) {
				mCombinedParams += "?";
				
				for (NameValuePair p : mParams) {
					String mParamString = p.getName() + "="
							+ URLEncoder.encode(p.getValue(), "UTF-8");
					
					if (mCombinedParams.length() > 1) {
						mCombinedParams += "&" + mParamString;
					} else {
						mCombinedParams += mParamString;
					}
				}
			}
			
			HttpPost mPostRequest = new HttpPost(mUrl + mCombinedParams);

			// add headers
			for (NameValuePair h : mHeaders) {
				mPostRequest.addHeader(h.getName(), h.getValue());
			}

			if (!mParams.isEmpty()) {
				mPostRequest.setEntity(new UrlEncodedFormEntity(mParams,
						HTTP.UTF_8));
			}

			// set the "request" var to "postRequest"
			mRequest = mPostRequest;
			
			commit();
			
			break;
		}
		}
	}

	private void commit() {
		HttpClient mClient = new DefaultHttpClient();

		HttpResponse mHttpResponse;
		
		Log.d("ExecuteRequest", mRequest.getURI().toASCIIString());
		
		try {
			mHttpResponse = mClient.execute(mRequest);
		
			mHttpResponse.getStatusLine().getStatusCode();
		
			mMessage = mHttpResponse.getStatusLine().getReasonPhrase();

			HttpEntity mEntity = mHttpResponse.getEntity();

			if (mEntity != null) {

				InputStream mInputStream = mEntity.getContent();
				
				String mResponse = convertStreamToString(mInputStream);
				
				Bundle mResponseBundle = new Bundle();
				
				mResponseBundle.putString("result", mResponse);
				
				mReceiver.send(mMethod, mResponseBundle);
				// Closing the input stream will trigger connection release
				
				mInputStream.close();
			}

		} catch (ClientProtocolException e) {
			mClient.getConnectionManager().shutdown();
			
			e.printStackTrace();
		} catch (IOException e) {
			mClient.getConnectionManager().shutdown();
			
			e.printStackTrace();
		}
	}

	private static String convertStreamToString(InputStream mInputStream) {

		BufferedReader mReader = new BufferedReader(new InputStreamReader(mInputStream));
		
		StringBuilder mStringBuilder = new StringBuilder();

		String mLine = null;
		
		try {
			while ((mLine = mReader.readLine()) != null) {
				mStringBuilder.append(mLine + "\n");
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				mInputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return mStringBuilder.toString();
	}
}
